home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / opengl / xlib / skeeter.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  22.9 KB  |  1,006 lines

  1. /*
  2.  * Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #include <stdio.h>
  18. #include <math.h>
  19. #include <GL/gl.h>
  20. #include <GL/glu.h>
  21. #include <GL/glx.h>
  22. #include <X11/Xlib.h>
  23. #include <X11/Xutil.h>
  24. #include <X11/keysym.h>
  25. #include <X11/cursorfont.h>
  26.  
  27. #include "skeeter.h"
  28.  
  29. /*
  30.  * attribute list for an RGB double buffered visual, with
  31.  * red, green, blue, and depth components
  32.  */
  33. static int attributeList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, 
  34.     GLX_RED_SIZE, 1,
  35.     GLX_GREEN_SIZE, 1,
  36.     GLX_BLUE_SIZE, 1,
  37.     GLX_DEPTH_SIZE, 1,
  38.     None };
  39.  
  40. int REDRAW = True;
  41. /*
  42.  * overlay plane visual attribute list
  43.  */
  44. static int al2[] = {GLX_LEVEL, 2,  None };
  45.  
  46. /*
  47.  * popup plane visual attribute list
  48.  */
  49. static int al1[] = {GLX_LEVEL, 1,  None };
  50.  
  51.  
  52. /*
  53.  * function to wait for a window to map
  54.  */
  55. static Bool WaitForNotify (Display *d, XEvent *e, char *arg)
  56. {
  57.     return (e->type == MapNotify) && (e->xmap.window == (Window) arg);
  58. }
  59.  
  60.  
  61. /*
  62.  * functions in this file
  63.  */
  64. void drawScene();
  65. void updateFlightParams();
  66. void pull();
  67. void drawCD();
  68. void gluErrorHandler();
  69. void makeCD();
  70. void drawBackground();
  71. void makeSkeeter();
  72. void initStruct();
  73. void newParams();
  74. void parseArgs();
  75.  
  76.  
  77.  
  78. main(int argc, char **argv)
  79. {
  80.  
  81.     XVisualInfo *vi;              /* X Visual  */
  82.     XVisualInfo *ovi;              /* X Visual  */
  83.  
  84.     Colormap cmap, ocmap;         /* X Colormap */
  85.     XSetWindowAttributes swa;     /* X Window Attributes */
  86.     XEvent event;                 /* X event             */
  87.     Window root_win;
  88.     char    xlat[20];
  89.     int     nchar = 20;
  90.     KeySym  key;
  91.     XComposeStatus cs;
  92.     XWindowAttributes winattrs;
  93.     
  94.     XColor  spix, pixel;
  95.     float fx, fy;
  96.     int num;
  97.     XMotionEvent  *motion;
  98.     XButtonEvent  *button;
  99.     static char cur[] = {0x0f, 0x0f};
  100.     XColor color;
  101.     Pixmap source;
  102.     int looper, now;
  103.  
  104.  
  105.     if (argc >1)
  106.         parseArgs(argc, argv);
  107.  
  108.     dpy = XOpenDisplay (0);
  109.     XSynchronize(dpy, True);
  110.  
  111.   /* 
  112.    * get a regular, double buffer, rgb visual 
  113.    * if we can't get it, big trouble, so bail out!
  114.    */
  115.     vi = glXChooseVisual (dpy, DefaultScreen(dpy), attributeList);
  116.     if (vi == NULL) {
  117.         printf("\n can't get requested visual type, bye...\n");
  118.         exit(0);
  119.         }
  120.  
  121.    /* 
  122.     * create a GLX context
  123.     */
  124.     cx = glXCreateContext (dpy, vi, None, GL_TRUE);
  125.  
  126.    /* 
  127.     * create a colormap using this visual 
  128.     */
  129.     cmap = XCreateColormap (dpy, RootWindow(dpy, vi->screen), vi->visual,
  130.                             AllocNone);
  131.  
  132.   /* 
  133.    *create an X Window 
  134.    */
  135.     swa.colormap = cmap;
  136.     swa.border_pixel = 1;
  137.     swa.event_mask = StructureNotifyMask;
  138.  
  139.     source = XCreatePixmapFromBitmapData(dpy, DefaultRootWindow(dpy),
  140.                                          cur, 1, 1, 0, 0, 1);
  141.     swa.cursor = XCreatePixmapCursor(dpy, source, source,
  142.                                         &color, &color, 0, 0);
  143.  
  144.     win = XCreateWindow (dpy, RootWindow(dpy,vi->screen), 
  145.                          0, 0, WINSIZE, WINSIZE,
  146.                          0, vi->depth, InputOutput, vi->visual,
  147.                          CWCursor | CWBorderPixel | 
  148.                          CWColormap|CWEventMask, &swa);
  149.  
  150.  
  151.     XMapWindow (dpy,win);
  152.  
  153.    /*
  154.     * wait for window to map so that we can start drawing into
  155.     * it.
  156.     */
  157.     XIfEvent(dpy, &event, WaitForNotify, (char *) win);
  158.  
  159.   /*
  160.    * now try to create an overlay window 
  161.    * the scheme is as follows:
  162.    *       - first try to get a level 2 visual, one in the overlay planes.
  163.    *      if that fails...
  164.    *    - try to get a level 1 visual, one in the popup planes.  
  165.    *      if that fails, just do all drawing in the normal planes
  166.    */
  167.  
  168.     ovi = glXChooseVisual (dpy, DefaultScreen(dpy), al2);
  169.  
  170.     if (ovi == NULL) {
  171.         printf("\n can't get requested overlay visual type...\n");
  172.         ovi = glXChooseVisual (dpy, DefaultScreen(dpy), al1);
  173.         if (ovi)
  174.             fprintf(stderr, "got popup plane window!\n");
  175.         }
  176.     else
  177.        fprintf(stderr, "got overlay plane window!\n");
  178.  
  179.     if (ovi == NULL) {
  180.         printf("\n can't get popup visual either, using regular visual...\n");
  181.         }
  182.  
  183.     if (ovi) {
  184.         USE_OVERLAY = True;
  185.        /* 
  186.         * we have an overlay visual, so 
  187.         * create a GLX context, along with the rest of the junk
  188.         * we need to create a window with this viusal
  189.         */
  190.         ocx = glXCreateContext (dpy, ovi, None, GL_TRUE);
  191.  
  192.        /* create a colormap using this visual */
  193.         ocmap = XCreateColormap (dpy, RootWindow(dpy, ovi->screen), ovi->visual,
  194.                                 AllocNone);
  195.  
  196.        /* create a X Window */
  197.         swa.colormap = ocmap;
  198.         swa.border_pixel = 0;
  199.         swa.win_gravity = UnmapGravity;
  200.         swa.bit_gravity = NorthWestGravity;
  201.         swa.background_pixel = BlackPixel(dpy, ovi->screen);
  202.  
  203.         owin = XCreateWindow (dpy, win, 0, 0, WINSIZE, WINSIZE,
  204.                              0, ovi->depth, InputOutput, ovi->visual,
  205.                              CWBorderPixel|CWColormap|CWEventMask, &swa);
  206.     
  207.  
  208.         XMapWindow (dpy,owin);
  209.  
  210.         }
  211.  
  212.     /* install the colormap windows property so that overlay colormap
  213.      * takes hold when we move cursor into window
  214.      */
  215.      
  216.      winList[0] = win;
  217.      winList[1] = owin;
  218.      
  219.      if (USE_OVERLAY) {
  220.          winList[1] = owin;
  221.          num = 2;
  222.          }
  223.      else
  224.          num = 1; 
  225.  
  226.     XSetWMColormapWindows(dpy, win, winList, num);
  227.  
  228.  /*
  229.   * get the 'white' pixel value, we will need this
  230.   * to set colormap index for overlay drawing
  231.   */
  232.  
  233.     if (USE_OVERLAY) {
  234.         XAllocNamedColor(dpy, ocmap, "white", &spix, &pixel);
  235.         WHITE_PIXEL_NUM = pixel.pixel;
  236.         XAllocNamedColor(dpy, ocmap, "RED", &spix, &pixel);
  237.         RED_PIXEL_NUM = pixel.pixel;
  238.         XAllocNamedColor(dpy, ocmap, "GRAY", &spix, &pixel);
  239.         BLACK_PIXEL_NUM = pixel.pixel;
  240.         }
  241.  
  242.   /* connect the context to the window */
  243.     if (!glXMakeCurrent(dpy, win, cx) == GL_TRUE) {
  244.         return 0;
  245.     }
  246.  
  247.  
  248.  
  249.  /*
  250.   * get the window size and location so that we can
  251.   * make the cylinder track the mouse movements *somewhat* acurately
  252.   */
  253.  
  254.     XGetWindowAttributes(dpy, win, &winattrs);
  255.     xorigin = winattrs.x;
  256.     yorigin = winattrs.y;
  257.     width = winattrs.width;
  258.     height = winattrs.height;
  259.  
  260.  /*
  261.   * starting location of skeeter, my choice
  262.   */
  263.     xloc = 100;
  264.     yloc = 100;
  265.  
  266.   /*
  267.    * finally, some OpenGL stuff!!
  268.    * set up zbuffer depth test, projection & model matrices, light models,
  269.    * and don't forget to turn on the light!
  270.    */
  271.    glViewport(0, 0, width, height);
  272.    glEnable(GL_DEPTH_TEST);
  273.    glDepthFunc(GL_LEQUAL);
  274.  
  275.  
  276.   /*
  277.    * set up projection matrix; we will use perspective projection
  278.    * and set our eye point 10 z units away, in effect, you will be
  279.    * shootin' from your chair, dead on!
  280.    */
  281.    glMatrixMode(GL_PROJECTION);
  282.    glLoadIdentity();
  283.  
  284.    gluPerspective(95.0, 1.0, 0.5, ZDEPTH);
  285.    gluLookAt(0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
  286.  
  287.   /*
  288.    * perspective set, model matrix stuff from now on...
  289.    */
  290.    glMatrixMode(GL_MODELVIEW);
  291.  
  292.    glTranslatef(0.0, 0.0, -4.0);
  293.  
  294.   /*
  295.    * let there be light!
  296.    */
  297.    glLightfv(GL_LIGHT1, GL_POSITION, lpos);
  298.    glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
  299.    glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
  300.    glLightfv(GL_LIGHT1, GL_SPECULAR, specular);
  301.  
  302.    glLightfv(GL_LIGHT2, GL_POSITION, l2_lpos);
  303.    glLightfv(GL_LIGHT2, GL_AMBIENT, l2_ambient);
  304.    glLightfv(GL_LIGHT2, GL_DIFFUSE, l2_diffuse);
  305.    glLightfv(GL_LIGHT2, GL_SPECULAR, l2_specular);
  306.    glLightf(GL_LIGHT2, GL_SPOT_CUTOFF, 45.0);
  307.    glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, l2_direction);
  308.    glLightf(GL_LIGHT2, GL_SPOT_EXPONENT, 80);
  309.  
  310.    glLightfv(GL_LIGHT3, GL_POSITION, lpos);
  311.    glLightfv(GL_LIGHT3, GL_POSITION, l3_lpos);
  312.    glLightfv(GL_LIGHT3, GL_AMBIENT, l3_ambient);
  313.    glLightfv(GL_LIGHT3, GL_DIFFUSE, l3_diffuse);
  314.    glLightfv(GL_LIGHT3, GL_SPECULAR, l3_specular);
  315.    glLightf(GL_LIGHT3, GL_SPOT_CUTOFF, 90.0);
  316.    glLightf(GL_LIGHT3, GL_SPOT_EXPONENT, 100);
  317.  
  318.    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
  319.    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, alm);
  320.    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); 
  321.  
  322.    glEnable(GL_LIGHTING);
  323.  
  324.    glEnable(GL_LIGHT3);
  325.  
  326.    if (num_lights > 1)
  327.        glEnable(GL_LIGHT2);
  328.  
  329.    if (num_lights > 2)
  330.        glEnable(GL_LIGHT3);
  331.  
  332.   /*
  333.    * now set up the matrix stuff for the overlay window.
  334.    * since not much going on here as far as 3D stuff,
  335.    * just keep it simple, -1 to +1 in X and Y, no Z component
  336.    * since we don't do any depth stuff in the overlay planes 
  337.    * anyway
  338.    */
  339.    if (USE_OVERLAY) {
  340.        glXMakeCurrent(dpy, owin, ocx); 
  341.        glViewport(0, 0, width, height);
  342.        glMatrixMode(GL_PROJECTION);
  343.        glLoadIdentity();
  344.        glOrtho(-1, 1, -1, 1, 0, 0);
  345.        glMatrixMode(GL_MODELVIEW);
  346.        }
  347.  
  348.   /*
  349.    * set X input stuff
  350.    */
  351.    XSelectInput(dpy, win, ExposureMask |StructureNotifyMask |
  352.                        ButtonPressMask | Button1MotionMask |
  353.                SubstructureNotifyMask | KeyPressMask |
  354.                        KeyReleaseMask | ButtonReleaseMask );
  355.  
  356.  
  357.    if (USE_OVERLAY) 
  358.        XSelectInput(dpy, owin, ExposureMask |StructureNotifyMask |
  359.                            ButtonPressMask | Button1MotionMask |
  360.                SubstructureNotifyMask | KeyPressMask |
  361.                            KeyReleaseMask | ButtonReleaseMask );
  362.  
  363.   /*
  364.    * if we are not using overlay drawing, set the overlay drawing
  365.    * window to the main planes window
  366.    */
  367.    if (!USE_OVERLAY) {
  368.        owin = win;
  369.        ocx = cx;
  370.        }
  371.  
  372.   glXMakeCurrent(dpy, win, cx);
  373.  
  374.   glClearColor(0.0, 0.0, 0.0, 0.0);
  375.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  376.  
  377.   makeCD();
  378.  
  379.   if (DO_BACKGROUND)
  380.       drawBackground();
  381.  
  382.   glXSwapBuffers(dpy, win);
  383.  
  384.   glXMakeCurrent(dpy, owin, ocx);
  385.   makeSkeeter();
  386.  
  387.   glXMakeCurrent(dpy, win, cx);
  388.  
  389.  /*
  390.   * initialize data structures
  391.   */
  392.  
  393.   initStruct();
  394.  
  395.   /*
  396.    * the dreaded X Event loop...
  397.    */
  398.    looper = now = 0;
  399.    while (1) {
  400.  
  401.        if (XPending(dpy)) {
  402.             XNextEvent(dpy, &event);
  403.             switch (event.type) {
  404.         case Expose:
  405.  
  406.                     glXMakeCurrent(dpy, owin, ocx);
  407.                     glClearIndex(0);
  408.                     glClear(GL_COLOR_BUFFER_BIT);
  409.  
  410.                     drawScene();
  411.                     drawSkeeter(xloc, yloc, WHITE_PIXEL_NUM, True);
  412.  
  413.             break;
  414.  
  415.          case ConfigureNotify:
  416.                    {
  417.                      int newwidth, newheight;
  418.                   /*
  419.                    * get window size in case of a resize...
  420.                    */
  421.                     XGetWindowAttributes(dpy, win, &winattrs);
  422.                     xorigin = winattrs.x;
  423.                     yorigin = winattrs.y;
  424.                     width = winattrs.width;
  425.                     height = winattrs.height;
  426.  
  427.                   /*
  428.                    * clear overlay window
  429.                    */
  430.                     if (USE_OVERLAY) {
  431.                         XResizeWindow(dpy, owin, width, height);
  432.                         glXMakeCurrent(dpy, owin, ocx);
  433.                         glViewport(0, 0, width, height);
  434.                         drawSkeeter(xloc, yloc, WHITE_PIXEL_NUM, True);
  435.                         }
  436.  
  437.                     glXMakeCurrent(dpy, win, cx);
  438.                     glViewport(0, 0, width, height);
  439.                     }
  440.  
  441.                     now = True;
  442.  
  443.             break;
  444.  
  445.                 case ButtonPress:
  446.                     button = (XButtonEvent *) &event;
  447.                     drawSkeeter(button->x, button->y, RED_PIXEL_NUM, True);
  448.                     REDRAW = False;
  449.                     break;
  450.  
  451.                 case ButtonRelease:
  452.                     REDRAW = True;
  453.                     break;
  454.  
  455.  
  456.         case KeyPress:
  457.                     XLookupString((XKeyEvent *) &event, xlat, nchar, &key, &cs);
  458.  
  459.                     switch (key) {
  460.  
  461.                         case XK_Escape:
  462.                             printf("\n bye...\n");
  463.                             exit(0);
  464.                             break;
  465.  
  466.                         case XK_space:
  467.                            pull();
  468.                            break;
  469.                         }
  470.  
  471.                     break;
  472.  
  473.  
  474.         case MotionNotify:
  475.                     motion = (XMotionEvent *) &event;
  476.                     drawSkeeter(motion->x, motion->y, WHITE_PIXEL_NUM, False);
  477.                     xloc = motion->x;
  478.                     yloc = motion->y;
  479.             break;
  480.  
  481.         default:
  482.             break;
  483.  
  484.                 }
  485.  
  486.              }
  487.  
  488.              if (REDRAW) {
  489.                 updateFlightParams();
  490.                 drawScene();
  491.                 }
  492.  
  493.             }
  494.  
  495. }
  496.  
  497.  
  498.  
  499. /*
  500.  * routine to draw the SKEETER, in the overlay planes if
  501.  * available
  502.  */
  503.  
  504. GLUquadricObj  *head, *rightEye, *leftEye, *body1, *body2, *body3;
  505.  
  506. drawSkeeter(int ix, int iy, int color, int now)
  507. {
  508.  
  509.   static int doMe = 1;
  510.   
  511.   int i; 
  512.   float x, y;
  513.   float v[2];
  514.  
  515. /*
  516.  * little slight-of-hand here.  X generates a truck load of events
  517.  * for cursor movements.  to get good performance, we will only process
  518.  * say every 10th cursor motion event, unless we are directed to do it
  519.  * 'now'.  an example of when we would want to redraw cross hair 'now'
  520.  * would be when the window is resized
  521.  *            
  522.  */
  523.  
  524.  
  525.   if (!now) {
  526.  
  527.       doMe++;
  528.       if ((doMe % 10) != 0)
  529.           return;
  530.       else
  531.           doMe = 1;
  532.       }
  533.  
  534.  
  535.  /*
  536.   *  we need to map the X window x and y coordinates to fit into
  537.   *  our overlay window space -1 to 1 in both X and Y
  538.   */
  539.   x = (float) ((((float) ix) - (((float)width)/2.0)) / (((float)width)/2.0));
  540.   y = (float) (( (((float)height)/2.0) - ((float) iy)) / (((float)height)/2.0));
  541.  
  542.  
  543.  /*
  544.   * make overlay window current and clear
  545.   */
  546.   glXMakeCurrent(dpy, owin, ocx);
  547.  
  548.  
  549.   if (USE_OVERLAY) {
  550.       glClearIndex(0);
  551.       glClear(GL_COLOR_BUFFER_BIT);
  552.       glIndexi(color);
  553.       }
  554.   else
  555.       glColor3b(1, 0, 0);
  556.  
  557.  
  558.  /*
  559.   * push down a matrix, multiply in a translation to current X and Y
  560.   * positions and call the SKEETER display list
  561.   */
  562.  
  563.   glPushMatrix();
  564.  
  565.      glTranslatef(x, y, 0.0);
  566.      glCallList(SKEETER_LIST);
  567.  
  568.   glPopMatrix();
  569.  
  570. }
  571.  
  572.  
  573. /*
  574.  * routine to make a 'skeeter display list
  575.  */
  576. void
  577. makeSkeeter()
  578. {
  579.  
  580.      glNewList(SKEETER_LIST, GL_COMPILE);
  581.  
  582.      glPushMatrix();
  583.  
  584.        glScalef(.1, .1, .0);
  585.  
  586.        if (!head)
  587.            head = gluNewQuadric();
  588.  
  589.        if (!rightEye)
  590.            rightEye = gluNewQuadric();
  591.  
  592.        if (!leftEye)
  593.            leftEye = gluNewQuadric();
  594.  
  595.        if (!body1)
  596.            body1 = gluNewQuadric();
  597.  
  598.        if (!body2)
  599.            body2 = gluNewQuadric();
  600.  
  601.        if (!body3)
  602.            body3 = gluNewQuadric();
  603.  
  604.            gluQuadricCallback(rightEye, GLU_ERROR, gluErrorHandler);
  605.            gluQuadricCallback(leftEye, GLU_ERROR, gluErrorHandler);
  606.            gluQuadricCallback(head, GLU_ERROR, gluErrorHandler);
  607.            gluQuadricCallback(body1, GLU_ERROR, gluErrorHandler);
  608.            gluQuadricCallback(body2, GLU_ERROR, gluErrorHandler);
  609.            gluQuadricCallback(body3, GLU_ERROR, gluErrorHandler);
  610.  
  611.            glIndexi(BLACK_PIXEL_NUM);
  612.  
  613.            gluDisk(head, 0.0, 0.5, 10.0, 10.0);
  614.  
  615.            glIndexi(RED_PIXEL_NUM);
  616.            glPushMatrix();
  617.                glTranslatef(-0.2, 0.4, 0.0);
  618.                gluDisk(rightEye, 0.0, 0.25, 10.0, 10.0);
  619.            glPopMatrix();
  620.  
  621.            glPushMatrix();
  622.                glTranslatef(-0.2, -0.4, 0.0);
  623.                gluDisk(leftEye, 0.0, 0.25, 10.0, 10.0);
  624.            glPopMatrix();
  625.  
  626.            glIndexi(BLACK_PIXEL_NUM);
  627.            glPushMatrix();
  628.                glTranslatef(0.5, 0.0, 0.0);
  629.                gluDisk(body1, 0.0, 0.4, 10.0, 10.0);
  630.            glPopMatrix();
  631.  
  632.            glPushMatrix();
  633.                glTranslatef(0.9, 0.0, 0.0);
  634.                gluDisk(body2, 0.0, 0.4, 10.0, 10.0);
  635.            glPopMatrix();
  636.  
  637.            glPushMatrix();
  638.                glTranslatef(1.3, 0.0, 0.0);
  639.                gluDisk(body3, 0.0, 0.4, 10.0, 10.0);
  640.            glPopMatrix();
  641.  
  642.            glBegin(GL_LINES);
  643.                 glVertex3f(0.4, 0.0, 0.0);
  644.                 glVertex3f(0.6, 1.0, 0.0);
  645.                
  646.                 glVertex3f(0.4, 0.0, 0.0);
  647.                 glVertex3f(0.6, -1.0, 0.0);
  648.  
  649.                 glVertex3f(0.9, 0.0, 0.0);
  650.                 glVertex3f(1.1, 1.0, 0.0);
  651.                
  652.                 glVertex3f(0.9, 0.0, 0.0);
  653.                 glVertex3f(1.1, -1.0, 0.0);
  654.  
  655.                 glVertex3f(1.3, 0.0, 0.0);
  656.                 glVertex3f(1.5, 1.0, 0.0);
  657.                
  658.                 glVertex3f(1.3, 0.0, 0.0);
  659.                 glVertex3f(1.5, -1.0, 0.0);
  660.            glEnd();
  661.  
  662.            glIndexi(WHITE_PIXEL_NUM);
  663.            glBegin(GL_TRIANGLES);
  664.                 glVertex3f(0.5, 0.2, 0.0);
  665.                 glVertex3f(1.0, 0.2, 0.0);
  666.                 glVertex3f(2.0, 0.9, 0.0);
  667.  
  668.                 glVertex3f(0.5, -0.2, 0.0);
  669.                 glVertex3f(1.0, -0.2, 0.0);
  670.                 glVertex3f(2.0, -0.9, 0.0);
  671.            glEnd();
  672.  
  673.      glPopMatrix();
  674.  
  675.    
  676.    glPopMatrix();
  677.  
  678.    glEndList();
  679.  
  680.  
  681. }
  682.  
  683. float rotAngle = 0.0;
  684.  
  685. /*
  686.  * update the scene.  first clear back and z buffers, then draw the
  687.  * cd
  688.  */
  689. void
  690. drawScene()
  691. {
  692.     int i;
  693.  
  694.     glXMakeCurrent(dpy, win, cx);
  695.  
  696.     glClearColor(0.0, 0.0, 0.0, 0.0);
  697.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  698.  
  699.     rotAngle+=15;
  700.  
  701.     if (DO_BACKGROUND) 
  702.         glCallList(BACKGROUND_LIST);
  703.  
  704.     for (i = 0; i < num_cd; i++) {
  705.          glPushMatrix();
  706.            glTranslatef(cd_info[i].posX, cd_info[i].posY, cd_info[i].posZ);
  707.            glRotatef(rotAngle, 1.0, 0.0, 0.0);
  708.            glCallList(CD1_LIST);
  709.          glPopMatrix();
  710.          }
  711.  
  712.  
  713.     glXSwapBuffers(dpy, win);
  714. }
  715.  
  716.  
  717. /*
  718.  * draw a cd.  a cd consists of several disks.  the big one is shiny silver,
  719.  * the others are supposed to be clear plastic, so we will use alpha
  720.  * blending transparency
  721.  */
  722. void
  723. drawCD(GLUquadricObj *cp)
  724. {
  725.  
  726.  if (!cp) {
  727.      cp = gluNewQuadric();
  728.      gluQuadricCallback(cp, GLU_ERROR, gluErrorHandler);
  729.      }
  730.  
  731.  
  732.      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mambient);
  733.      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mdiffuse);
  734.      glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mspecular);
  735.      glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
  736.  
  737.      gluDisk(cp, 2.0, 5.0, 50.0, 50.0);
  738.  
  739.   /* 
  740.    * enable alpha blending to simulate the clear plastic part
  741.    * of the cd in the center and the outer edge
  742.    */
  743.      glEnable(GL_BLEND);
  744.      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  745.  
  746.      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ma2);
  747.      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, md2);
  748.      glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, ms2);
  749.  
  750.      gluDisk(cp, 5.0, 5.25, 50.0, 50.0);
  751.      gluDisk(cp, 0.9, 1.75, 50.0, 50.0);
  752.  
  753.      glBlendFunc(GL_ONE, GL_ZERO);
  754.      glDisable(GL_BLEND);
  755.  
  756.  
  757.  
  758.  
  759. }
  760.  
  761. void
  762. gluErrorHandler()
  763. {
  764.  
  765.     fprintf(stderr, "%s\n", gluErrorString(glGetError()));
  766. }
  767.  
  768.  
  769. void
  770. makeCD()
  771. {
  772.  
  773.  
  774.     glNewList(CD1_LIST, GL_COMPILE);
  775.  
  776.        glMaterialfv(GL_FRONT, GL_AMBIENT, gambient);
  777.        glMaterialfv(GL_FRONT, GL_DIFFUSE, gdiffuse);
  778.        glMaterialfv(GL_FRONT, GL_SPECULAR, gspecular);
  779.        glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
  780.  
  781.        drawCD(cp1);
  782.     glEndList();
  783.  
  784. }
  785.  
  786. void
  787. pull()
  788. {
  789.  
  790.  /*
  791.   * start raining cdroms down
  792.   */
  793.  
  794.  
  795.   updateFlightParams();
  796.  
  797. }
  798.  
  799. #include <time.h>
  800.  
  801. void
  802. updateFlightParams()
  803. {
  804.  
  805.    int i;
  806.  
  807.    for (i = 0; i < num_cd; i++) {
  808.  
  809.         if (cd_info[i].state == NONE)
  810.             newParams(i);
  811.  
  812.         if (cd_info[i].posZ <= -85) {
  813.             cd_info[i].state = NONE;
  814.             newParams(i);
  815.             }
  816.  
  817.         cd_info[i].posZ += cd_info[i].ZInc;
  818.         }
  819.  
  820.  
  821.  
  822. }
  823.  
  824.  
  825. /*
  826.  * the checkerboard background
  827.  */
  828. void
  829. drawBackground()
  830. {
  831.  
  832.    float i, j, next;
  833.  
  834.    next = True;
  835.  
  836.  
  837.    glNewList(BACKGROUND_LIST, GL_COMPILE);
  838.  
  839.    glDisable(GL_LIGHTING);
  840.  
  841.    glBegin(GL_QUADS);
  842.  
  843.    for (j = -100; j < 100; j+=10) {
  844.       for (i = -100; i < 100; i+=10) {
  845.  
  846.            if (next) {
  847.                glColor3f(0.31, 0.16, 1.0);
  848.                next = !next;
  849.                }
  850.            else {
  851.                glColor3f(0.15, 0.15, 1.0);
  852.                next = !next;
  853.                }
  854.            
  855.            glVertex3f(i, j, -85.0); 
  856.            glVertex3f(i+10.0, j, -85.0); 
  857.            glVertex3f(i+10.0, j+10.0, -85.0); 
  858.            glVertex3f(i, j+10.0, -85.0); 
  859.  
  860.            }
  861.        next = !next;
  862.  
  863.       }
  864.    glEnd();
  865.   
  866.    glEnable(GL_LIGHTING);
  867.  
  868.    glEndList();
  869.  
  870. }
  871.  
  872. void
  873. initStruct()
  874. {
  875.  
  876.  int i;
  877.  
  878.  for (i = 0; i < MAX_DROPS; i++) {
  879.  
  880.     cd_info[i].state = NONE;
  881.        }
  882.  
  883.  
  884. }
  885.  
  886. void
  887. newParams(int ix)
  888. {
  889.  
  890.    time_t     tloc;
  891.    double     x, y, z;
  892.    long     xt, yt, zt;
  893.  
  894.    static       int firstTime = 0;
  895.  
  896.  
  897.        
  898.        if (!firstTime) {
  899.            time(&tloc);
  900.            srandom((long) tloc);
  901.            firstTime = 1;
  902.            }
  903.  
  904.        x = random();
  905.        y = random();
  906.        z = random();
  907.  
  908.        xt = (x / 100.0);
  909.        xt = xt * 100;
  910.        x = (x - xt)/10;
  911.  
  912.        yt = (y / 100.0);
  913.        yt = yt * 100;
  914.        y = (y - yt)/10;
  915.  
  916.        zt = (z / 100.0);
  917.        zt = zt * 100;
  918.        z = (z - zt)/10;
  919.  
  920.  
  921.  
  922.       cd_info[ix].XInc = x/10;
  923.  
  924.       cd_info[ix].YInc = y/10;
  925.  
  926.       cd_info[ix].ZInc = -z/10;
  927.  
  928.     /*
  929.      * for some variety, if x is od, start at a negative X position
  930.      */
  931.       if ((((int)x) % 2) != 0)
  932.           cd_info[ix].posX = -x;
  933.       else
  934.           cd_info[ix].posX = x;
  935.  
  936.     /*
  937.      * for some variety, if y is even, start at a negative Y position
  938.      */
  939.       if ((((int)y) % 2) != 0)
  940.           cd_info[ix].posY = y;
  941.       else
  942.           cd_info[ix].posY = -y;
  943.  
  944.       cd_info[ix].posZ = 10;
  945.  
  946.       cd_info[ix].state = FALLING;
  947.  
  948. #ifdef DEBUG
  949. fprintf(stderr, "\n new cd[%d] posX: %f  posY: %f  posZ: %f\n",
  950.         ix,cd_info[ix].posX, cd_info[ix].posY,cd_info[ix].posZ);
  951. fprintf(stderr, "\n            XInc: %f  YInc: %f  ZInc: %f\n",
  952.         cd_info[ix].XInc, cd_info[ix].YInc,cd_info[ix].ZInc);
  953. #endif
  954. }
  955.  
  956. void
  957. parseArgs(int argc, char **argv)
  958. {
  959.  
  960.    int i, argOk;
  961.  
  962.    argOk = False;
  963.  
  964.    for (i = 1; i < argc; i++) {
  965.  
  966.         if (strcmp(argv[i], "-nb") == 0) {
  967.             DO_BACKGROUND = False;
  968.             argOk = True;
  969.             }
  970.  
  971.      if (strcmp(argv[i], "-n") == 0)  {
  972.             if (i+1 < argc) {
  973.                 num_cd = atoi(argv[i+1]);
  974.                 i++;
  975.                 }
  976.             else 
  977.                 num_cd = 0;
  978.  
  979.             if ((num_cd > 0) && (num_cd <= MAX_DROPS))
  980.                 argOk = True;
  981.             }
  982.  
  983.  
  984.         if (strcmp(argv[i], "-l") == 0)  {
  985.             if (i+1 < argc) {
  986.                 num_lights = atoi(argv[i+1]);
  987.                 i++;
  988.                 }
  989.             else
  990.                 num_lights = 0;
  991.  
  992.             if ((num_lights > 0) && (num_lights <= MAX_LIGHTS))
  993.                 argOk = True;
  994.             }
  995.  
  996.  
  997.         if (argOk != True) {
  998.             fprintf(stderr, 
  999.                 "\nusage: %s [-nb -n <number of cd's> -l <number of lights>]\n"
  1000.                           , argv[0]);
  1001.             exit(0);
  1002.             }
  1003.    
  1004.         }
  1005. }
  1006.